package hello

import (
	"math"
	"strconv"
	"appengine"
	"appengine/datastore"
)

type Ingredient struct {
	ProductId int64
	RecipeId int64
	Id int64
	Name string
	Count float64
	Unit Unit
}

type Unit int

func listAllUnits() []Unit {
	return []Unit{NONE, GLASS, GRAM, PCS, TABLESPOON, TEASPOON}
}

func unitName(unit Unit) string {
	switch unit {
		case NONE: return "По вкусу"
		case GLASS: return "стакан"
		case GRAM: return "г."
		case PCS: return "шт."
		case TABLESPOON: return "ст.л."
		case TEASPOON: return "ч.л."
		default: return "unknown Unit type"
	}
	return ""
}

func printCount(i Ingredient) string {
	var count string
	_, fraction := math.Modf(i.Count)
	if fraction == 0 {
		count = strconv.FormatFloat(i.Count, 'f', 0, 64)
	} else {
		count = strconv.FormatFloat(i.Count, 'f', 1, 64)
	}
	
	var s string;
	if i.Unit == NONE {
		s = unitName(i.Unit)
	} else {
		s = count + " " + unitName(i.Unit)
		if i.Count > 1 && i.Unit == GLASS {
			s += "а"
		}
	}
	return s
}

const (
	NONE = Unit(1)
	GLASS = Unit(2)
	GRAM = Unit(3)
	PCS = Unit(4)
	TABLESPOON = Unit(5)
	TEASPOON = Unit(6)
)

func createIngredientKey(c *appengine.Context) (key *datastore.Key) {
	key = datastore.NewIncompleteKey(*c, "Ingredient", nil)
	return
}

func restoreIngredientKey(c *appengine.Context, id int64) (key *datastore.Key) {
	key = datastore.NewKey(*c, "Ingredient", "", id, nil)
	return
}

func saveIngredient(c *appengine.Context, productId int64, recipeId int64, ingredient *Ingredient) (key *datastore.Key) {
	ingredient.ProductId = productId
	ingredient.RecipeId = recipeId
	key, err := datastore.Put(*c, createIngredientKey(c), ingredient)
	panicIfErr(err)
	ingredient.Id = key.IntID()
	key, err = datastore.Put(*c, key, ingredient)
	panicIfErr(err)
	return
}

func updateIngredient(c *appengine.Context, id int64, ingredient *Ingredient) {
	_, err := datastore.Put(*c, restoreIngredientKey(c, id), ingredient)
	panicIfErr(err)
}

func deleteIngredient(c *appengine.Context, id int64) {
	err := datastore.Delete(*c, restoreIngredientKey(c, id))
	panicIfErr(err)
}

func listAllIngredients(c *appengine.Context, recipeId int64) ([]*Ingredient) {
	return listIngredients(c, recipeId, -1)
}

func listIngredients(c *appengine.Context, recipeId int64, limit int) ([]*Ingredient) {
	q := datastore.NewQuery("Ingredient").Filter("RecipeId =", recipeId).Limit(limit).Order("-Count")
	ingredients := make([]*Ingredient, 0)
	_, err := q.GetAll(*c, &ingredients)
	panicIfErr(err)
	return ingredients
}